﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Ext.Net;
using Ext.Net.MVC;
using Sharp.DataTransferObject;
using Sharp.Platform.Mvc;
using Sharp.Platform.Interface;
using Sharp.Platform.List;

namespace Sharp.Web
{
    /// <summary>
    /// ExtNet模板适配器
    /// </summary>
    public class ExtNetTemplateProvider : ITemplateProvider
    {
        #region 新增
        /// <summary>
        /// 新增
        /// </summary>
        /// <returns></returns>
        public string Create(object model)
        {
            if (model == null)
            {
                return string.Empty;
            }
            StringBuilder sb = new StringBuilder();

            Rendering(sb, model, "添加");

            return sb.ToString();
        }
        #endregion

        #region 编辑
        /// <summary>
        /// 编辑
        /// </summary>
        /// <returns></returns>
        public string Edit(object model)
        {
            if (model == null)
            {
                return string.Empty;
            }
            StringBuilder sb = new StringBuilder();

            Rendering(sb, model, "修改");

            return sb.ToString();
        }
        #endregion

        #region 详情
        /// <summary>
        /// 详情
        /// </summary>
        /// <returns></returns>
        public string Details(object model)
        {
            if (model == null)
            {
                return string.Empty;
            }
            StringBuilder sb = new StringBuilder();
            Rendering(sb, model, "详情");
            return sb.ToString();
        }
        #endregion

        #region 主页
        /// <summary>
        /// 主页
        /// </summary>
        /// <returns></returns>
        public string Index(object model)
        {
            if (model == null)
            {
                return string.Empty;
            }

            if (model is ISharpTreeList)
            {
                return IndexTree(model);
            }

            var dataList = (ISharpList)model;
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("@model {0}\r\n", model.GetType().FullName);
            sb.AppendLine("@using Ext.Net");
            sb.AppendLine("@using Ext.Net.MVC");
            sb.AppendLine("@using Sharp.Web");
            sb.AppendLine("@{");
            sb.AppendLine("    var x = Html.X();");
            sb.AppendLine("}");

            sb.AppendLine("@(");
            sb.AppendLine(" x.GridPanel()");
            if (!dataList.Feature.HasFlag(ListFeature.HiddenToolButton))
            {
                sb.AppendLine("            .TopBar(x.Toolbar().Items(");

                //渲染工具栏按钮
                sb.AppendLine(string.Join(",", dataList.GetToolButtons(model).Select(x => x.Html)));

                sb.AppendLine("                ,new ToolbarFill(),");
                sb.AppendLine("                x.TextField().Width(300).FieldLabel(\"搜索\").LabelWidth(50)");
                sb.AppendLine("                    .Triggers(");
                sb.AppendLine("                        x.FieldTrigger().Icon(TriggerIcon.Clear).HideTrigger(true),");
                sb.AppendLine("                        x.FieldTrigger().Icon(TriggerIcon.Search)");
                sb.AppendLine("                    )");
                sb.AppendLine(
                    "                    .Listeners(ls => { ls.TriggerClick.Fn = \"App.Grid.searchFieldTriggerClick\"; })");
                sb.AppendLine("                ))");
            }

            sb.AppendLine("            .Plugins(");
            sb.AppendLine("                x.GridFilters()");
            sb.AppendLine("                    .Local(false)");
            sb.AppendLine("                    .Filters(");
            List<string> filters = new List<string>();
            foreach (var property in model.GetType().GetProperties())
            {
                if (property.PropertyType != typeof(string))
                {
                    continue;
                }
                filters.Add("x.StringFilter().DataIndex(Model, d => d." + property.Name + ")");
            }
            sb.AppendLine(string.Join(",\r\n", filters.ToArray()));
            sb.AppendLine("                    )");
            sb.AppendLine("            )");


            sb.AppendLine("            .Store(x.StoreForModel()");
            sb.AppendLine(
                "                .Proxy(x.AjaxProxy().Url(Url.Action(\"GetPaged\")).Post().Reader(x.JsonReader().RootProperty(\"data\")))");
            if (dataList.Feature.HasFlag(ListFeature.Paging))
            {
                sb.AppendLine("                .RemoteSort(true).RemotePaging(true).PageSize(25)");
            }


            sb.AppendLine("                .SorterFor(Model, m => m.Id, Ext.Net.SortDirection.DESC)");
            sb.AppendLine("                )");
            if (dataList.Feature.HasFlag(ListFeature.MultiSelect))
            {
                sb.AppendLine("            .SelectionModel(x.CheckboxSelectionModel())");
            }
            sb.AppendLine("            .ColumnModel(");


            List<string> columns = new List<string>();
            if (dataList.Feature.HasFlag(ListFeature.RowNumber))
            {
                columns.Add("x.RowNumbererColumn().Align(ColumnAlign.End).Width(60)");
            }
            foreach (var property in model.GetType().GetProperties())
            {
                if (!property.GetCustomAttributes(false).Any()) { continue; }
                if (property.PropertyType == typeof(MasterDataDTO))
                {
                    #region 主数据显示
                    var template =

                            property.GetCustomAttributes(typeof(TemplateColumnAttribute), false).FirstOrDefault() as TemplateColumnAttribute;
                    if (template == null)
                    {
                        var column = property.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault() as ColumnAttribute;
                        var text = property.Name;
                        if (column != null)
                        {
                            text = column.Text;
                        }
                        columns.Add(
                            string.Format(
                                "x.TemplateColumn().DataIndex(\"{0}\").Text(\"{1}\").TemplateString(\"<tpl for=\\\".\\\">{{{0}.Name}}</tpl>\")",
                                property.Name, text));
                    }
                    else
                    {
                        columns.Add(
                            string.Format(
                                "x.TemplateColumn().DataIndex(\"{0}\").Text(\"{1}\").TemplateString(\"<tpl for=\\\".\\\">{{{0}.Name}}</tpl>\")",
                                property.Name, template.Text));
                    }

                    #endregion
                }
                else
                {
                    columns.Add("x.ColumnFor(m => m." + property.Name + ")");
                }
            }
            sb.AppendLine(string.Join(",\r\n", columns.ToArray()));
            sb.AppendLine("            )");
            if (dataList.Feature.HasFlag(ListFeature.Paging))
            {
                sb.AppendLine("            .BottomBar(x.PagingToolbar().ItemsFromPartial(\"~/Views/Shared/_PagingToolbarPartial.cshtml\"))");
            }
            sb.AppendLine("            .EmptyText(\"无数据。\")");
            sb.AppendFormat("            .View(x.GridView().StripeRows({0}).TrackOver(true))", (!dataList.Feature.HasFlag(ListFeature.GridLineDisable)).ToString().ToLower());
            sb.AppendLine("            .Listeners(li => { li.ItemDblClick.Fn = \"App.Grid.OnModuleGridItemDblClick\"; })");
            sb.AppendLine(")");
            return sb.ToString();
        }

        private string IndexTree(object model)
        {
            var dataList = (ISharpList)model;
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("@model {0}\r\n", model.GetType().FullName);
            sb.AppendLine("@using Ext.Net");
            sb.AppendLine("@using Ext.Net.MVC");
            sb.AppendLine("@using Sharp.Web");
            sb.AppendLine("@{");
            sb.AppendLine("    var x = Html.X();");
            sb.AppendLine("}");

            sb.AppendLine("@(");
            sb.AppendLine(" x.TreePanel().UseArrows(false).AutoScroll(true).Mode(TreePanelMode.Remote).RootVisible(false).Border(false).RootVisible(false).Animate(false).FolderSort(false)");
            if (!dataList.Feature.HasFlag(ListFeature.HiddenToolButton))
            {
                sb.AppendLine("            .TopBar(x.Toolbar().Items(");

                //渲染工具栏按钮
                sb.AppendLine(string.Join(",", dataList.GetToolButtons(model).Select(x => x.Html)));

            }

            sb.AppendLine("            .Features(");
            sb.AppendLine("                x.GridFilters()");
            sb.AppendLine("                    .Local(false)");
            sb.AppendLine("                    .Filters(");
            List<string> filters = new List<string>();
            foreach (var property in model.GetType().GetProperties())
            {
                if (property.PropertyType != typeof(string))
                {
                    continue;
                }
                filters.Add("x.StringFilter().DataIndex(Model, d => d." + property.Name + ")");
            }
            sb.AppendLine(string.Join(",\r\n", filters.ToArray()));
            sb.AppendLine("                    )");
            sb.AppendLine("            )");


            sb.AppendLine("            .Store(x.StoreForModel()");
            sb.AppendLine(
                "                .Proxy(x.AjaxProxy().Url(Url.Action(\"GetPaged\")).Post().Reader(x.JsonReader().Root(\"data\")))");
            if (dataList.Feature.HasFlag(ListFeature.Paging))
            {
                sb.AppendLine("                .RemoteSort(true).RemotePaging(true).PageSize(25)");
            }


            sb.AppendLine("                .SorterFor(Model, m => m.Id, Ext.Net.SortDirection.DESC)");
            sb.AppendLine("                )");
            if (dataList.Feature.HasFlag(ListFeature.MultiSelect))
            {
                sb.AppendLine("            .SelectionModel(x.CheckboxSelectionModel())");
            }
            sb.AppendLine("            .ColumnModel(");


            List<string> columns = new List<string>();
            if (dataList.Feature.HasFlag(ListFeature.RowNumber))
            {
                columns.Add("x.RowNumbererColumn().Align(ColumnAlign.End).Width(60)");
            }
            foreach (var property in model.GetType().GetProperties())
            {
                if (!property.GetCustomAttributes(false).Any()) { continue; }
                if (property.PropertyType == typeof(MasterDataDTO))
                {
                    #region 主数据显示
                    var template =

                            property.GetCustomAttributes(typeof(TemplateColumnAttribute), false).FirstOrDefault() as TemplateColumnAttribute;
                    if (template == null)
                    {
                        var column = property.GetCustomAttributes(typeof(ColumnAttribute), false).FirstOrDefault() as ColumnAttribute;
                        var text = property.Name;
                        if (column != null)
                        {
                            text = column.Text;
                        }
                        columns.Add(
                            string.Format(
                                "x.TemplateColumn().DataIndex(\"{0}\").Text(\"{1}\").TemplateString(\"<tpl for=\\\".\\\">{{{0}.Name}}</tpl>\")",
                                property.Name, text));
                    }
                    else
                    {
                        columns.Add(
                            string.Format(
                                "x.TemplateColumn().DataIndex(\"{0}\").Text(\"{1}\").TemplateString(\"<tpl for=\\\".\\\">{{{0}.Name}}</tpl>\")",
                                property.Name, template.Text));
                    }

                    #endregion
                }
                else
                {
                    columns.Add("x.ColumnFor(m => m." + property.Name + ")");
                }
            }
            sb.AppendLine(string.Join(",\r\n", columns.ToArray()));
            sb.AppendLine("            )");
            if (dataList.Feature.HasFlag(ListFeature.Paging))
            {
                sb.AppendLine("            .BottomBar(x.PagingToolbar().ItemsFromPartial(\"~/Views/Shared/_PagingToolbarPartial.cshtml\"))");
            }
            sb.AppendLine("            .EmptyText(\"无数据。\")");
            sb.AppendFormat("            .View(x.GridView().StripeRows({0}).TrackOver(true))", (!dataList.Feature.HasFlag(ListFeature.GridLineDisable)).ToString().ToLower());
            sb.AppendLine("            .Listeners(li => { li.ItemDblClick.Fn = \"App.Grid.OnModuleGridItemDblClick\"; })");
            sb.AppendLine(")");
            return sb.ToString();
        }
        #endregion

        #region 渲染界面

        /// <summary>
        /// 渲染界面
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="model"></param>
        /// <param name="title"></param>
        private void Rendering(StringBuilder sb, object model, string title)
        {
            sb.AppendFormat("@model {0}\r\n", model.GetType().FullName);
            sb.AppendLine("@using Ext.Net");
            sb.AppendLine("@using Ext.Net.MVC");
            sb.AppendLine("@using Sharp.Web");
            sb.AppendLine("@{");
            sb.AppendLine("    var x = Html.X();");
            sb.AppendLine("}");
            sb.AppendLine("@(");
            sb.AppendFormat("        x.Window().Layout(LayoutType.Fit).Title(\"{0}\")\r\n", title);
            sb.AppendLine("            .CloseAction(CloseAction.Destroy)");

            ISharpForm from = model as ISharpForm;
            if (from == null)
            {
                sb.AppendLine("            .Width(720)");
            }
            else
            {
                sb.AppendFormat("            .Width({0})", from.UI.Width);
            }
            sb.AppendLine("            .Items(");
            sb.AppendLine("                x.FormPanel().Default()");
            //if (from != null && from.UI.LayoutType == (int)LayoutType.Column)
            {
                sb.Append(".Layout(LayoutType.Column)");
            }
            sb.Append(".Items(");

            RendingEditing(sb, model);

            sb.AppendLine(")");
            sb.AppendLine("                    .Buttons(");
            sb.AppendFormat("\r\n                        x.Button().Text(\"提交\").Icon(Icon.Disk).Hidden({0})", (title == "详情").ToString().ToLower());
            sb.AppendLine("                            .DirectEvents(de =>");
            sb.AppendLine("                            {");
            sb.AppendLine("                                de.Click.Before = \"App.Edit.submitReady\";");
            sb.AppendLine("                                de.Click.Action = \"Save\";");
            sb.AppendLine("                                de.Click.EventMask.ShowMask = true;");
            sb.AppendLine("                                de.Click.EventMask.Msg = \"正在提交...\";");
            sb.AppendLine("                                de.Click.EventMask.MinDelay = 1000;");
            sb.AppendLine("                                de.Click.Success = \"App.Edit.PostBackSuccess\";");
            sb.AppendLine("                            }),");
            sb.AppendLine("                        x.Button().Text(\"关闭\").Icon(Icon.Cancel).OnClientClick(\"App.Edit.CloseWindow(this)\")");
            sb.AppendLine("                    )");
            sb.AppendLine("            )");

            sb.AppendLine(")");
        }

        private void RendingEditing(StringBuilder sb, object model)
        {
            bool fieldInserted = false;
            foreach (var property in model.GetType().GetProperties())
            {
                var customAttributes = property.GetCustomAttributes(false);
                if (!customAttributes.Any())
                {
                    continue;
                }
                if (customAttributes.Any(x => x is DataTypeAttribute))
                {
                    var dataType = customAttributes.First(x => x is DataTypeAttribute) as DataTypeAttribute;

                    if (dataType.DataType == DataType.Html)
                    {
                        sb.Append("x.HtmlEditorFor(m => m." + property.Name + ").ColumnWidth(1).Padding(4),");
                    }
                    else if (dataType.DataType == DataType.Html)
                    {
                        sb.Append("x.DateFieldFor(m => m." + property.Name + ").ColumnWidth(.5).Padding(4),");
                    }
                    else if (dataType.DataType == DataType.Upload)
                    {
                        sb.AppendFormat("x.FileUploadField().DataIndex(\"{0}\").Text(\"{1}\").ColumnWidth(1).Padding(4),", property.Name, "");
                    }
                    else if (dataType.DataType == DataType.Date)
                    {
                        sb.Append("x.DateFieldFor(m => m." + property.Name + ").ColumnWidth(.5).Padding(4),");
                    }
                    else if (dataType.DataType == DataType.DateTime)
                    {
                        sb.Append("x.DateFieldFor(m => m." + property.Name + ").ColumnWidth(.5).Padding(4),");
                    }
                    else if (dataType.DataType == DataType.Time)
                    {
                        sb.Append("x.TimeFieldFor(m => m." + property.Name + ").ColumnWidth(.5).Padding(4),");
                    }
                    else if (dataType.DataType == DataType.MultilineText)
                    {
                        sb.Append("x.TextAreaFor(m => m." + property.Name + ").ColumnWidth(1).Padding(4),");
                    }
                }
                else if (customAttributes.Any(x => x is HiddenInputAttribute))
                {
                    sb.Append("x.HiddenFor(m => m." + property.Name + "),");
                }
                else if (customAttributes.Any(x => x is CustomFieldAttribute))
                {
                    var customField = (CustomFieldAttribute) customAttributes.First(x => x is CustomFieldAttribute);
                    if (customField.FieldType == FieldType.OrgList)
                    {
                        sb.Append("x.DropDownFieldFor(m => m." + property.Name + ").OrgList(Model.OrgTree,\"" + customField.ValueHiddenName + "\").Editable(false).ColumnWidth(.5).Padding(4),");
                        sb.AppendFormat("x.HiddenFor(f=>f.{0}),", customField.ValueHiddenName);
                    }
                }
                else
                {
                    sb.Append("x.TextFieldFor(m => m." + property.Name + ").ColumnWidth(.5).Padding(4),");
                }
                fieldInserted = true;
            }

            if (fieldInserted)
            {
                sb.Remove(sb.Length - 1, 1);
            }
        }
        private void RendingReading(StringBuilder sb, object model) { }
        #endregion
    }
}